function createDatePicker(div, date, config) {
	var cfg = {};
	if(config !== undefined) {
		$.extend(cfg, config);
	}
	var datePicker = el(div).jqxDateTimeInput({
		width: 100,
		height: 24,
		value: date,
		formatString: 'dd.MM.yyyy',
		firstDayOfWeek: 1,
		allowNullDate: true,
		showFooter: true,
		todayString: 'Сегодня',
		clearString: 'Очистить'
	});
	if(cfg.onChangeFn !== undefined) {
		datePicker.on('valuechanged', function(event) {
			cfg.onChangeFn(event.args.date);
		});
	}
	return datePicker;
};

function createSimpleButton(div, w, h, onClickFn) {
	var btn = el(div).jqxButton({ width: w, height: h});
	if(onClickFn !== undefined) {
		btn.click(onClickFn);
	}
	return btn;
};

function createLinkButton(div, onClickFn) {
	return el(div).click(onClickFn);
};

function createCheckBox(div, checked, onChangeFn) {
	var checkBox = el(div).jqxCheckBox({ checked: checked });
	if(onChangeFn !== undefined) {
		checkBox.change(function(event) {
			onChangeFn(event.args.checked);
		});
	}
	return checkBox;
};

function createNumberInput(div, w, h) {
	el(div).jqxNumberInput({ width: w, height: h, inputMode: 'simple', spinButtons: true });
};

function createTextArea(div, w, h, hint) {
	var ta = el(div).jqxInput({
		placeHolder: hint? hint: '',
		height: h,
		width: w
	});
	ta.autosize();
	return ta;
}

function createTooltip(div, contentHtml) {
	return el(div).tooltipster({
		content: contentHtml,
		contentAsHTML: true,
		delay: 0,
		position: 'bottom',
		trigger: 'click',
		theme: 'tooltipster-light'
	});
};

function createSortableHeader(headersMap, field, tableDiv, title, sorting) {
	var elementId = tableDiv + 'Header_' + field;
	var header = '<span id="' + elementId + '" class="header-sortable">' + title;
	if(field === sorting.field) {
		header += '<span class="sort-arrow">';
		if(sorting.isDesc()) {
			header += '&#x21E1;';
		} else {
			header += '&#x21E3';
		}
		header += '</span>';
	}
	header += '</span>';
	headersMap[field] = { html: header, id: elementId };
};

function Html(element) {
	this.html = function() {
		return element;
	};
};

function GridCell(content, config) {
	var cfg = {
		classes: []
	};
	$.extend(cfg, config? config: {});
	this.html = function() {
		return '<td class="' + cfg.classes.join(' ') + '">' + content.html() + '</td>';
	};

	this.setup = function(property, value) {
		cfg[property] = value;
	};
};

function GridRow(config) {
	var cfg = {
		classes: []
	};
	$.extend(cfg, config? config: {});
	this.hbox = new HBox();

	this.addCell = function(cellContent, config) {
		if(typeof cellContent == 'string') {
			cellContent = new Html(cellContent);
		}
		this.hbox.addItem(cellContent, config);
		return this;
	};

	this.setup = function(property, value) {
		cfg[property] = value;
	};

	this.html = function(colspan) {
		return '<tr><td class="' + cfg.classes.join(' ') + '" ' + (colspan? 'colspan="' + colspan + '"': '') + '>' + this.hbox.html() + '</td></tr>';
	};
};

function Grid(div, config) {
	var self = this;
	var cfg = {
		width: '100%',
		classes: ['grid'],
		collapsable: false
	};
	this.expanded = true;
	$.extend(cfg, config? config: {});
	this.header = null;
	this.footer = null;
	this.rows = [];

	this.setHeader = function(header) {
		this.header = header;
		return this;
	};

	this.setFooter = function(footer) {
		this.footer = footer;
		return this;
	};

	this.addRow = function(row) {
		this.rows.push(row);
		return this;
	};

	this.html = function() {
		var html = '<table width="' + cfg.width + '" class="' + cfg.classes.join(' ') + '">';
		var colspan = 1;
		if (this.header != null) {
			html += '<thead class="panel-header"><tr><td>' + this.header + '</td>';
			if(cfg.collapsable) {
				html += '<td width="25px" class="panel-collapser"><span id="' + div + 'Collapse">' + (this.expanded? '−': '+') + '</span></td>';
				colspan = 2;
			}
//			− ∧ ∨ ⋀ ⋁
			html += '</tr></thead>';
		}
		if (this.footer != null) {
			html += '<tfoot class="panel-footer"><tr><td colspan="' + colspan + '">' +
				this.footer + '</td></tr></tfoot>';
		}
		html += '<tbody>';
		$.each(this.rows, function(index, row) {
			html += row.html(colspan);
		});
		html += '</tbody></table>';
		return html;
	};

	this.render = function() {
		el(div).html(this.html());
		createLinkButton(div + 'Collapse', function() {
			self.toggleCollapse();
		});
		return this;
	};

	this.toggleCollapse = function() {
		this.expanded = !this.expanded;
//		this.render();
	};
};

function Table(div, config) {

	this.rows = [];
	var cfg = {
		cellspacing: 0
	};
	$.extend(cfg, config? config: {});

	this.newRow = function() {
		this.rows.push([]);
		return this;
	};

	this.addCell = function(content, config) {
		var cell = { content: (typeof content == 'string'? new Html(content): content), classes: [] };
		$.extend(cell, config);
		this.rows[this.rows.length - 1].push(cell);
		return this;
	};

	this.html = function() {
		var html = '<table class="table-layout" cellspacing="' + cfg.cellspacing + '">';
		$.each(this.rows, function(row, cells) {
			html += '<tr>';
			$.each(cells, function(col, cell) {
				html += '<td' + (cell.colspan? ' colspan=' + cell.colspan: '')
					+ (cell.rowspan? ' rowspan=' + cell.rowspan: '')
					+ ' class="' + cell.classes.join(' ') + '">'
					+ cell.content.html() + '</td>';
			});
			html += '</tr>';
		});
		return html + '</table>';
	};

	this.render = function() {
		el(div).html(this.html());
		return this;
	};
};

function Box(div) {
	this.cells = [];

	this.addItem = function(item, config) {
		var content = (typeof item == 'string'? new Html(item): item);
		this.cells.push(new GridCell(content, config));
		return this;
	};

	this.render = function() {
		el(div).html(this.html());
		return this;
	};
};

function HBox(div) {
	var box = new Box(div);
	$.extend(this, box);

	this.html = function() {
		var html = '<table class="hbox"><tr>';
		$.each(this.cells, function(index, cell) {
			html += cell.html();
		});
		return html + '</tr></table>';
	};
};

function VBox(div) {
	var box = new Box(div);
	$.extend(this, box);

	this.html = function() {
		var html = '<table class="vbox">';
		$.each(this.cells, function(index, cell) {
			html += '<tr>' + cell.html() + '</tr>';
		});
		return html + '</table>';
	};
};